package com.example.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.common.constant.ProductConstant;
import com.example.product.dao.AttrAttrgroupRelationDao;
import com.example.product.dao.AttrGroupDao;
import com.example.product.dao.CategoryDao;
import com.example.product.entity.AttrAttrgroupRelationEntity;
import com.example.product.entity.AttrGroupEntity;
import com.example.product.entity.CategoryEntity;
import com.example.product.util.CategoryUtils;
import com.example.product.vo.AttrRespVo;
import com.example.product.vo.AttrVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.utils.PageUtils;
import com.example.common.utils.Query;

import com.example.product.dao.AttrDao;
import com.example.product.entity.AttrEntity;
import com.example.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Slf4j
@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Autowired
    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;
    @Autowired
    private CategoryDao categoryDao;
    @Autowired
    private AttrGroupDao attrGroupDao;
    @Autowired
    private CategoryUtils categoryUtils;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params,String type, Long catId) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();

        // 0-销售属性，1-基本属性
        if (type.equals("base")) {
            queryWrapper.eq("attr_type", ProductConstant.AttrType.ATTR_TYPE_BASE_ATTR.getCode() );
        } else {
            queryWrapper.eq("attr_type",ProductConstant.AttrType.ATTR_TYPE_SALE_ATTR.getCode());
        }

        if (catId != 0) {
            queryWrapper = queryWrapper.eq("catelog_id",catId);
        }

        String key = (String)params.get("key");

        if (!StringUtils.isEmpty(key)) {
            queryWrapper = queryWrapper.and(qw -> {
                qw.eq("attr_id",key).or().like("attr_name",key);
            });
        }

        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                queryWrapper
        );

        List<AttrEntity> records = page.getRecords();
        // 给每一个属性设置所属分类和所属分组
        // 注： 电商系统不做关联查询，因为数据量大的时候，笛卡尔积会非常大，这是很危险的操作
        List<AttrRespVo> attrRespVos = records.stream().map(record -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(record, attrRespVo);

            if (record != null) {
                // 设置所属分类
                CategoryEntity categoryEntity = categoryDao.selectOne(new QueryWrapper<CategoryEntity>().eq("cat_id", record.getCatelogId()));
                if (categoryEntity != null) {
                    attrRespVo.setCatelogName(categoryEntity.getName());
                }
                // 设置所属分组
                // 因为销售属性没有分组，所以当查询的是销售属性的时候就不用设置属性分组了
                if ("base".equals(type)) {
                    AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", record.getAttrId()));
                    if (attrAttrgroupRelationEntity != null) {
                        AttrGroupEntity attrGroupEntity = attrGroupDao.selectOne(new QueryWrapper<AttrGroupEntity>().eq("attr_group_id", attrAttrgroupRelationEntity.getAttrGroupId()));
                        if (attrGroupEntity != null) {
                            attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                        }
                    }
                }
            }

            return attrRespVo;
        }).collect(Collectors.toList());

        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(attrRespVos);
        return pageUtils;
    }

    @Transactional
    @Override
    public void saveAttr(AttrVo attrVo) {
        AttrEntity attrEntity = new AttrEntity();
        // 保存属性
        BeanUtils.copyProperties(attrVo,attrEntity);
        // 1.@@@@@@@@@@AttrEntity(attrId=null,
        log.info("1.@@@@@@@@@@{}",attrEntity);
        baseMapper.insert(attrEntity);
        // 保存属性所属分组
        // 2.@@@@@@@@@@AttrEntity(attrId=18,
        log.info("2.@@@@@@@@@@{}",attrEntity);
        // 当添加的属性是销售属性时，没有属性分组，即AttrGroupId为空，所以就可以不需要保存属性所属分组了
        if (attrVo.getAttrType() == ProductConstant.AttrType.ATTR_TYPE_BASE_ATTR.getCode()) {
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            attrAttrgroupRelationDao.insert(attrAttrgroupRelationEntity);
        }
    }

    @Override
    public AttrRespVo getInfoById(Long attrId) {
        AttrEntity attrEntity = baseMapper.selectById(attrId);
        AttrRespVo attrRespVo = new AttrRespVo();
        if (attrEntity != null) {
            BeanUtils.copyProperties(attrEntity,attrRespVo);
            if (attrEntity != null) {
                // 判断是否是基本属性，如果是基本属性则设置分组id,销售属性没有分组所以不设置
                if (attrEntity.getAttrType() == ProductConstant.AttrType.ATTR_TYPE_BASE_ATTR.getCode()) {
                    // 设置分组id
                    AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = attrAttrgroupRelationDao
                            .selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>()
                                    .eq("attr_id", attrEntity.getAttrId()));
                    if (attrAttrgroupRelationEntity != null) {
                        attrRespVo.setAttrGroupId(attrAttrgroupRelationEntity.getAttrGroupId());
                    }
                }
            }
            // 设置属性分类id路径，为回显级联菜单使用
            List<Long> path = new ArrayList<>();
            categoryUtils.getCatelogPath(attrEntity.getCatelogId(),path);
            Collections.reverse(path);
            attrRespVo.setCatelogPath(path.toArray(new Long[path.size()]));
        }
        return attrRespVo;
    }

    @Transactional
    @Override
    public void updateAttrById(AttrVo attr) {
        // 1. 更新属性表
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);
        baseMapper.updateById(attrEntity);
        // 2. 更新属性分组关系表
        // 先判断属性是否为基本属性
        if (attr.getAttrType() == ProductConstant.AttrType.ATTR_TYPE_BASE_ATTR.getCode()) {
            if (attr != null) {
                // 判断该属性原来是否存在分组
                Integer count = attrAttrgroupRelationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
                if (count == 0) {
                    // 原来没有分组，则对该属性新增分组
                    AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
                    attrAttrgroupRelationEntity.setAttrId(attr.getAttrId());
                    attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());
                    attrAttrgroupRelationDao.insert(attrAttrgroupRelationEntity);
                } else {
                    // 原来该属性存在分组，则修改该属性分组
                    attrAttrgroupRelationDao.update(null,
                            new UpdateWrapper<AttrAttrgroupRelationEntity>()
                                    .set("attr_group_id",attr.getAttrGroupId())
                                    .eq("attr_id",attr.getAttrId()));
                }
            }
        }
    }

    @Override
    public PageUtils getGroupNoRelationAttr(Map<String, Object> params, Long attrGroupId) {
        // 1. 查询已经被当前分类下的分组关联的基本属性
        // 查询当前分组所属分类
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrGroupId);
        // 查询当前分类下有哪些分组
        IPage<AttrEntity> page = null;
        if (attrGroupEntity != null) {
            List<AttrGroupEntity> catelogs = attrGroupDao
                    .selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", attrGroupEntity.getCatelogId()));

            // 收集分组id
            if (catelogs != null && catelogs.size() > 0) {
                List<Long> attrGroupIds = catelogs.stream().map(item -> {
                    return item.getAttrGroupId();
                }).collect(Collectors.toList());

                // 查询已经被当前分类下的分组关联的基本属性
                List<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntities = attrAttrgroupRelationDao
                        .selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", attrGroupIds));

                // 2. 查询不包括第一步的基本属性的基本属性，而且是当前分组所属分类下的基本属性
                QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                        // 当前分类下的属性
                        .eq("catelog_id",attrGroupEntity.getCatelogId())
                        // 基本属性
                        .eq("attr_type", ProductConstant.AttrType.ATTR_TYPE_BASE_ATTR.getCode());

                if (attrAttrgroupRelationEntities != null && attrAttrgroupRelationEntities.size() > 0) {
                    // 收集属性id
                    List<Long> attrIds = attrAttrgroupRelationEntities.stream().map(item -> {
                        return item.getAttrId();
                    }).collect(Collectors.toList());
                    // 不包括已近被关联的属性
                    wrapper.notIn("attr_id",attrIds);
                }

                // 判断查询关键字是否为空
                String key = (String)params.get("key");
                if (!StringUtils.isEmpty(key)) {
                    wrapper.and(wp -> {
                        wp.eq("attr_id",key).or().like("attr_name",key);
                    });
                }
                page = this.page(
                        new Query<AttrEntity>().getPage(params),
                        wrapper
                );
            }
        }


        return new PageUtils(page);
    }
}